/*******************************************************************************
 * Copyright (c) 2002 Boris Pruessmann and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 *    Boris Pruessmann - Initial implementation.
 ******************************************************************************/
package net.sourceforge.perforce.ui.action;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import net.sourceforge.perforce.core.PerforceCorePlugin;
import net.sourceforge.perforce.core.PerforceException;
import net.sourceforge.perforce.core.api.IPerforceServer;
import net.sourceforge.perforce.core.api.IResolveResult;
import net.sourceforge.perforce.core.api.ResolveTypeEnum;
import net.sourceforge.perforce.core.internal.P4TeamProvider;
import net.sourceforge.perforce.core.resources.IP4File;
import net.sourceforge.perforce.ui.PerforceUIPlugin;
import net.sourceforge.perforce.ui.dialogs.AutoResolveDialog;
import net.sourceforge.perforce.ui.internal.Policy;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.team.core.TeamException;
import org.eclipse.ui.actions.WorkspaceModifyOperation;

/**
  * @version $Revision: 202 $
  * @author  <a href="mailto:bpruessmann@users.sourceforge.net">Boris Pruessmann</a>
  */
public class AutoResolveAction extends P4FileAction 
{
	// ------------------------------------------------------------------------------ Public Methods
	
	/** @see IActionDelegate#run(IAction) */
	public void run(IAction action) 
	{
		final IP4File[] files = getSelectedPerforceFiles();
		boolean enableReResolve = shouldEnableReResolve(files);
		
		AutoResolveDialog dialog = new AutoResolveDialog(getShell(), enableReResolve);
		if (dialog.open() != AutoResolveDialog.OK)
		{
			return;
		} 
		
		int tempOptions = (dialog.shouldReResolve()) ? IPerforceServer.RESOLVE_FORCE : 0;
		tempOptions &= 
			(dialog.shouldAttemptBinaryMerge()) ? IPerforceServer.RESOLVE_MERGE_BINARY : 0;
		 
		final Set skippedFiles = new HashSet();
		final ResolveTypeEnum resolveType = dialog.getResolveType();
		final int options = tempOptions;
		run(new WorkspaceModifyOperation()
		{
			public void execute(IProgressMonitor monitor)
				throws InvocationTargetException
			{
				monitor = Policy.monitorFor(monitor);
				monitor.beginTask("", files.length * 1000);                            //$NON-NLS-1$
					
				Set serverSet = new HashSet();
				List resolvedFiles = new ArrayList();			
				try
				{
					for (int i = 0; i < files.length && !monitor.isCanceled(); i++)
					{
						IP4File file = files[i];
						monitor.subTask(
							Policy.bind("AutoResolveAction.Resolving",                 //$NON-NLS-1$
							file.getName()));
						
						IPerforceServer server = file.getServer();
						IResolveResult[] resolveResults = 
							server.resolve(file.getDepotFilename(), resolveType, options);
						
						Policy.assertTrue(resolveResults.length == 1);						
						if (resolveResults[0].isSkipped())
						{
							skippedFiles.add(file);
						}
						else
						{
							serverSet.add(server);
							resolvedFiles.add(file.getLocation());
						}
						
						monitor.worked(500);
					}
				}
				catch (PerforceException e)
				{
					throw new InvocationTargetException(e);
				}
				finally
				{			
					try
					{
						IWorkspaceRoot root = PerforceUIPlugin.getWorkspace().getRoot();
						for (Iterator it = resolvedFiles.iterator(); it.hasNext();)
						{
							IPath location = (IPath) it.next();
							IFile file = root.getFileForLocation(location);
							if (file != null)
							{
								P4TeamProvider provider = P4TeamProvider.getProvider(file);
								
								file.refreshLocal(IFile.DEPTH_ZERO, null);
								provider.refreshState(
									new IFile[]{ file }, IFile.DEPTH_ZERO, null);
							}
							
							monitor.worked(500);
						}
					}
					catch (CoreException e)
					{
						PerforceUIPlugin.log(e.getStatus());
					}
					catch (TeamException e)
					{
						PerforceUIPlugin.log(e.getStatus());
					}
										
					IPerforceServer[] servers = 
						(IPerforceServer[]) serverSet.toArray(
							new IPerforceServer[serverSet.size()]);
					PerforceCorePlugin.getPlugin().broadcastChangelistStateChanges(servers);
							
					monitor.done();
				}
			}
		}, PROGRESS_DIALOG);
		
		Integer resolved = new Integer(files.length - skippedFiles.size());
		String message = Policy.bind("AutoResolveAction.statusMessage", resolved);     //$NON-NLS-1$
		MultiStatus status = 
			new MultiStatus(
				PerforceUIPlugin.ID,
				MultiStatus.INFO,
				message,
				null);
		for (Iterator it = skippedFiles.iterator(); it.hasNext();)
		{
			IP4File file = (IP4File) it.next();
			
			message = 
				Policy.bind("AutoResolveAction.wasSkipped", file.getDepotFilename());  //$NON-NLS-1$
			status.merge(new Status(Status.INFO, PerforceUIPlugin.ID, 0, message, null));			
		}
		
		String title = Policy.bind("AutoResolveAction.statusTitle");                   //$NON-NLS-1$
		if (status.isOK())
		{
			MessageDialog.openInformation(getShell(), title, status.getMessage());
		}
		else
		{
			ErrorDialog.openError(
				getShell(), 
				title, 
				Policy.bind("AutoResolveAction.statusErrorMessage"), //$NON-NLS-1$
				status);
		}
	}

	// --------------------------------------------------------------------------- Protected Methods

	/** @see PerforceAction#isEnabled() */
	protected boolean isEnabled() 
		throws PerforceException 
	{
		IP4File[] files = getSelectedPerforceFiles();
		for (int i = 0; i < files.length; i++)
		{
			IP4File file = files[i];
			if (!file.needsResolve())
			{
				return false;
			}
		}
				
		return true;
	}
	
	// ----------------------------------------------------------------------------- Private Methods
	
	/** Checks whether any of the given files already has been resolved. In that case, we want to 
	  * enable the re-resolve button of the AutoResolveDialog.
	  * 
	  * @param files array of IP4File to check
	  * @return true or false 
	  */
	private boolean shouldEnableReResolve(IP4File[] files)
	{
		for (int i = 0; i < files.length; i++)
		{
			if (files[i].isResolved())
			{
				return true;
			}			
		}
		
		return false;
	}
}
